#pragma once 
#include "Cond.hpp"
#include <iostream>
#include <pthread.h>
#include <queue>
using namespace std;
using namespace MutexModule;
using namespace CondModule;
const int N = 5;
template <class T>
class BlockQueue {
private:
    bool IsFull() { return _q.size() >= _cap; }
    bool IsEmpty() { return _q.empty(); }
public:
    BlockQueue(int cap = N)
    :_cap(cap), _csleep(0), _psleep(0) {}
    ~BlockQueue() {}
    void Equeue(const T& in) { // 生产者模型
        {
            LockGuard lockguard(_mutex);
            while(IsFull()) {
                _psleep++;
                cout << "生产者进入了休眠，个数是：" << _psleep << endl;
                _fullcond.Wait(_mutex);
                _psleep--;
            }
            _q.push(in);
            if(_csleep > 0) { // 有消费者在等待我们的任务，我们唤醒它
                _emptycond.Signal();
                cout << "唤醒我们的生产者" << endl;
            }
        }
    }
    T pop() { // 消费者模型
        T data;
        {
            LockGuard lockguard(_mutex);
            while(IsEmpty()) {
                _csleep++;
                _emptycond.Wait(_mutex);
                _csleep--;
            }
            data = _q.front();
            _q.pop();
            if(_psleep > 0) { // 有生产者在等待，就可以将其唤醒了
                _fullcond.Signal();
                cout << "唤醒我们的生产者" << endl;
            }
        }
        return data;
    }
private:
    queue<T> _q;
    int _cap;
    Mutex _mutex;
    Cond _fullcond;
    Cond _emptycond;
    int _csleep; // 消费者休眠个数
    int _psleep; // 生产者休眠个数
};